<template>
  <div class="container">
    <div class="markdown-body" v-html="markdownContent" ref="contentRef"></div>
    <div v-show="showCursor" class="cursor"></div>
  </div>
</template>

<script setup>
import "github-markdown-css/github-markdown-dark.css";
import { marked } from "marked";
import { computed, ref, reactive, onMounted, onUpdated } from "vue";
import hljs from "highlight.js";
import "highlight.js/styles/dark.css";
const props = defineProps({
  content: {
    type: String,
    required: true,
  },
  showCursor: {
    type: Boolean,
    default: false,
  },
});
marked.setOptions({
  // 去掉一些警告
  langPrefix: undefined,
  mangle: false,
  headerIds: false,
  highlight: function (code, lang) {
    // 这样写报一个意想不到的bug，有的时候lang不是'js',是'j'
    // if (lang && hljs.getLanguage(lang)) {
    //   return hljs.highlight(code, { language: lang }).value;
    // }
    // return hljs.highlight(code).value;
    // 直接这样
    return hljs.highlight(code, { language: "js" }).value;
  },
});
const markdownContent = computed(() => {
  return marked.parse(props.content);
});

const pos = reactive({ x: 0, y: 0 });
const contentRef = ref(null);

function getLastTextNode(dom) {
  // 需要文本节点
  const children = dom.childNodes;
  console.log(children);
  for (let i = children.length - 1; i >= 0; i--) {
    const node = children[i];
    console.log(node);
    // 去掉\n的节点
    if (node.nodeType === Node.TEXT_NODE && /\S/.test(node.nodeValue)) {
      // 去掉文本后面的\n
      node.nodeValue = node.nodeValue.replace(/\s+$/, "");
      return node;
    } else if (node.nodeType === Node.ELEMENT_NODE) {
      const last = getLastTextNode(node);
      if (last) {
        return last;
      }
    }
  }
  return null;
}

function updateCursor() {
  const contentDom = contentRef.value;
  const lastText = getLastTextNode(contentDom);
  // 零宽字符
  const textNode = document.createTextNode("\u200b");
  // 最后一个字符存在就放到最后面
  if (lastText) {
    lastText.parentElement.appendChild(textNode);
  } else {
    // 不存在就放在文档后面
    contentDom.appendChild(textNode);
  }
  const domRect = contentDom.getBoundingClientRect();
  // 文本节点，不能直接用getBoundingClientRect
  const range = document.createRange();
  range.setStart(textNode, 0);
  range.setEnd(textNode, 0);
  const rect = range.getBoundingClientRect();
  pos.x = rect.left - domRect.left;
  pos.y = rect.top - domRect.top;
  textNode.remove();
}
onMounted(updateCursor);
onUpdated(updateCursor);
</script>

<style lang="scss" scoped>
.markdown-body {
  background: inherit;
  line-height: 2;
  font-family: "Roboto Mono";
}
.container {
  position: relative;
  background-color: #000;
  min-height: 700px;
}
.cursor {
  content: "";
  position: absolute;
  width: 10px;
  height: 16px;
  background-color: #d5d9da;
  animation: toggle 0.6s infinite;
  opacity: 0;
  transform: translateY(3px);
  left: calc(v-bind("pos.x") * 1px);
  top: calc(v-bind("pos.y") * 1px);
}
@keyframes toggle {
  30% {
    opacity: 1;
  }
}
</style>
